package com.hyz.yuaiagent.app;

import com.hyz.yuaiagent.advisor.MyLoggerAdvisor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;

/**
 * LoveAppDemoWithToolCall 类用于演示如何使用聊天模型进行对话，同时集成工具调用功能。
 * 它通过 Spring 的 ChatClient 进行聊天，并可以利用工具注册配置来调用外部工具。
 */
@Component
public class LoveAppDemoWithToolCall {

    // 工具注册配置，用于配置和管理外部工具的调用
    private final ToolCallback[] allTools;
    // 聊天客户端，用于实际执行聊天和工具调用
    private final ChatClient chatClient;

    /**
     * 构造函数，用于初始化 LoveAppDemoWithToolCall 类。
     * 它接受一个 ChatModel 和一个 ToolRegistrationConfig 作为参数，
     * 并在构造过程中初始化 ChatClient。
     *
     * @param dashscopeChatMode 聊天模型，用于与用户进行对话
     * @param allTools          工具注册配置，用于配置和管理外部工具的调用
     */
    @Autowired
    public LoveAppDemoWithToolCall(ChatModel dashscopeChatMode,
                                   ToolCallback[] allTools) {

        // 初始化 ChatClient，设置默认的顾问为 MyLoggerAdvisor
        this.chatClient = ChatClient.builder(dashscopeChatMode)
                .defaultAdvisors(new MyLoggerAdvisor())
                .build();
        this.allTools = allTools;
    }

    /**
     * 执行与聊天模型的对话，同时可以调用外部工具。
     * 该方法接受用户的输入消息和对话的标识符作为参数，
     * 并使用这些信息来构建和发送聊天请求。
     *
     * @param msg 用户的输入消息
     * @param id  对话的标识符，用于跟踪和恢复对话上下文
     */
    public String doChatWithTools(String msg, String id) {
        // 构建聊天请求规范，包括用户消息、对话标识符和工具配置
        ChatClient.CallResponseSpec callResponseSpec = chatClient
                .prompt()
                .user(msg)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, id)
//                         来自上下文的聊天内存响应大小 如果为1 就是只能记忆1轮对话
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .tools(allTools)
                .call();

        return callResponseSpec.content();
    }
}
